package com.example.camunda.rest;

import cn.hutool.core.io.IoUtil;
import com.example.camunda.dto.DeploymentCreateFormData;
import com.example.camunda.dto.DeploymentDto;
import com.example.camunda.dto.DeploymentResourceDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.repository.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 流程部署
 *
 * @author heshao
 * @date 2021/11/9 14:59
 **/
@Api(tags = "二、流程部署")
@RestController
@RequestMapping("/deployment")
public class DeploymentController {

    private final RepositoryService repositoryService;

    public DeploymentController(RepositoryService repositoryService) {
        this.repositoryService = repositoryService;
    }

    @GetMapping
    @ApiOperation("查询所有流程部署")
    public Page<DeploymentDto> list(@RequestParam(defaultValue = "0") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {
        DeploymentQuery query = repositoryService.createDeploymentQuery();
        long count = query.count();
        List<Deployment> list = query.listPage(pageNum * pageSize, pageSize);
        List<DeploymentDto> dtoList = list.stream().map(DeploymentDto::from).collect(Collectors.toList());
        return new PageImpl<>(dtoList, PageRequest.of(pageNum, pageSize), count);
    }

    @PostMapping(value = "/create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation("创建流程部署")
    public DeploymentDto create(@Validated DeploymentCreateFormData payload) throws IOException {
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();

        MultipartFile data = payload.getData();
        deploymentBuilder.addInputStream(data.getOriginalFilename(), data.getInputStream());

        String deploymentName = payload.getDeploymentName();
        if (deploymentName != null) {
            deploymentBuilder.name(deploymentName);
        }

        String deploymentSource = payload.getDeploymentSource();
        if (deploymentSource != null) {
            deploymentBuilder.source(deploymentSource);
        }

        deploymentBuilder.enableDuplicateFiltering(true);
        DeploymentWithDefinitions deployment = deploymentBuilder.deployWithResult();
        return DeploymentDto.from(deployment);
    }

    @GetMapping("/{id}")
    @ApiOperation("查询流程部署")
    public DeploymentDto get(@PathVariable String id) {
        Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(id).singleResult();
        return DeploymentDto.from(deployment);
    }

    @DeleteMapping("/{id}")
    @ApiOperation("删除流程部署")
    public void delete(@PathVariable String id) {
        repositoryService.deleteDeployment(id);
    }

    @GetMapping("/{id}/resources")
    @ApiOperation("查询所有流程部署资源")
    public List<DeploymentResourceDto> getResources(@PathVariable String id) {
        List<Resource> resources = repositoryService.getDeploymentResources(id);
        return resources.stream().map(DeploymentResourceDto::from).collect(Collectors.toList());
    }

    @GetMapping("/{id}/resources/{resourceId}")
    @ApiOperation("查询流程部署资源")
    public DeploymentResourceDto getResource(@PathVariable String id, @PathVariable String resourceId) {
        List<Resource> resources = repositoryService.getDeploymentResources(id);
        Optional<Resource> first = resources.stream().filter(resource -> resourceId.equals(resource.getId())).findFirst();
        return first.map(DeploymentResourceDto::from).get();
    }

    @GetMapping("/{id}/resources/{resourceId}/data")
    @ApiOperation("查询流程部署资源")
    public void getResourceData(@PathVariable String id, @PathVariable String resourceId, HttpServletResponse response) throws IOException {
        List<Resource> resources = repositoryService.getDeploymentResources(id);
        Resource resource = resources.stream().filter(r -> resourceId.equals(r.getId())).findFirst().get();

        InputStream resourceStream = repositoryService.getResourceAsStreamById(id, resourceId);

        String filename = resource.getName();
        response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

        OutputStream out = response.getOutputStream();
        IoUtil.copy(resourceStream, out);

        IoUtil.close(resourceStream);

        IoUtil.flush(out);
        IoUtil.close(out);
    }
}
